Android에서 비디오 앱을 개발하고 쉐이더를 통해 카메라에서 비디오를 렌더링하고 필터링하기 위해 OpenGL을 사용합니다. 내 셰이더 중 하나는 두 개의 텍스처를 사용합니다. 하나는 카메라의 라이브 프레임이고 다른 하나는 이전 렌더링 패스 결과입니다. 따라서 그림을 두 번 렌더링해야합니다. 미리보기를 위해 화면을 표시하고 다음 렌더 패스를 위해 텍스처를 분리해야합니다. 그것을 달성하기 위해 프레임 버퍼 객체를 사용합니다. 여기 내 코드가 있습니다 : 초기화 프레임 버퍼 : private void initPredrawBuffer() {
GLES20.glActiveTexture(GLES20.GL_TEXTURE1);
prevBuffer = new int[1]; GLES20.glGenFramebuffers(1, prevBuffer, 0); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]);
prevTexture = new int[1]; GLES20.glGenTextures(1, prevTexture, 0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, mFrameWidth, mFrameHeight, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, prevTexture[0], 0);
int[] depthRenderbuffers = new int[1]; GLES20.glGenRenderbuffers(1, depthRenderbuffers, 0); GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]); GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, mFrameWidth, mFrameHeight); GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthRenderbuffers[0]);
int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) { throw new RuntimeException("Incomplete buffer"); } }
및 렌더링 : private void draw(boolean offScreen, float[] mvpMatrix, FloatBuffer vertexBuffer, int firstVertex, int vertexCount, int coordsPerVertex, int vertexStride, float[] texMatrix, FloatBuffer texBuffer, int textureId, int texStride) { GlUtil.checkGlError("draw start");
if (offScreen) GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, prevBuffer[0]); else GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
// Select the program. GLES20.glUseProgram(firstFrame && firstFrameProgram > 0 ? firstFrameProgram : mProgramHandle); GlUtil.checkGlError("glUseProgram");
// Set the texture. GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId);
// Copy the model / view / projection matrix over. GLES20.glUniformMatrix4fv(muMVPMatrixLoc, 1, false, mvpMatrix, 0); GlUtil.checkGlError("glUniformMatrix4fv");
// Copy the texture transformation matrix over. GLES20.glUniformMatrix4fv(muTexMatrixLoc, 1, false, texMatrix, 0); GlUtil.checkGlError("glUniformMatrix4fv");
// Enable the "aPosition" vertex attribute. GLES20.glEnableVertexAttribArray(maPositionLoc); GlUtil.checkGlError("glEnableVertexAttribArray");
// Connect vertexBuffer to "aPosition". GLES20.glVertexAttribPointer(maPositionLoc, coordsPerVertex, GLES20.GL_FLOAT, false, vertexStride, vertexBuffer); GlUtil.checkGlError("glVertexAttribPointer");
// Enable the "aTextureCoord" vertex attribute. GLES20.glEnableVertexAttribArray(maTextureCoordLoc); GlUtil.checkGlError("glEnableVertexAttribArray");
// Connect texBuffer to "aTextureCoord". GLES20.glVertexAttribPointer(maTextureCoordLoc, 2, GLES20.GL_FLOAT, false, texStride, texBuffer); GlUtil.checkGlError("glVertexAttribPointer");
// Setting Light Trails filter params if (mProgramType == ProgramType.TEXTURE_LIGHT_TRAILS && !firstFrame) { GLES20.glUniform1i(muTextureNew, 0); GlUtil.checkGlError("glUniform1i muTextureNew");
GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GlUtil.checkGlError("temp glActiveTexture");
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, prevTexture[0]); GlUtil.checkGlError("temp glBindTexture");
GLES20.glUniform1i(muTexturePrev, 1); GlUtil.checkGlError("glUniform1i muTexturePrev");
GLES20.glUniform1f(muLightTrailsExposure, lightTrailsKernel[0]); GlUtil.checkGlError("glUniform1f muLightTrailsExposure");
GLES20.glUniform1f(muLightTrailsEcho, lightTrailsKernel[1]); GlUtil.checkGlError("glUniform1f muLightTrailsEcho");
GLES20.glUniform1f(muLightTrailsLimit, lightTrailsKernel[2]); GlUtil.checkGlError("glUniform1f muLightTrailsLimit");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GlUtil.checkGlError("temp glActiveTexture"); }
// Draw the rect. GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, firstVertex, vertexCount); GlUtil.checkGlError("glDrawArrays");
GLES20.glFinish(); }
문제는 프레임 버퍼에 렌더링이 작동하지 않고 glReadPixels 항상 빈 배열을 반환한다는 것입니다. 화면에 렌더링이 잘 작동합니다.
|